package xyz.wadewhy.basicstest.juc;


import org.jetbrains.annotations.NotNull;
import org.springframework.util.Assert;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

import static org.apache.commons.lang3.time.DateUtils.addMonths;
import static org.apache.commons.lang3.time.DateUtils.addSeconds;

/**
 * Created by taoshao on 17/5/24.
 */
public class DateUtils {
    public static final String DATE_PATTERN = "yyyy-MM-dd";

    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public static final int DAYS_OF_WEEK = 7;
    public static final Date ORIGIN_DATE = new Date(1452441600000L);   //1452441600000  对应着的 2016-01-11 00:00:00
    public static final Long SECOND_OF_DAY = 1000 * 3600 * 24L;
    private static SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_PATTERN);

    private static SimpleDateFormat dateTimeFormat = new SimpleDateFormat(DATE_TIME_PATTERN);

    private DateUtils() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 获取本月第一天
     * @return
     */
    public static Date getFirstDayInMonth(Date date) {
        date = DateUtils.truncate(date, Calendar.MONTH);
        return date;
    }

    /**
     * 本月最后一天
     * @param date
     * @return
     */
    public static Date getLastDayInMonth(Date date) {
        date = org.apache.commons.lang3.time.DateUtils.ceiling(date, Calendar.MONTH);// 进位月份
        date = org.apache.commons.lang3.time.DateUtils.addMilliseconds(date, -1);
        return date;
    }

    /**
     * @param time
     * DateTimeFormatter 线程安全
     * @return
     */
    public static String getYYYYMMDDV2FromDate(Long time) {
        DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(time/1000, 0, ZoneOffset.ofHours(8));
        // 将 Date 转换成 JDK 8 中的时间类型 LocalDateTime
//        LocalDateTime localDateTime =
//                LocalDateTime.ofInstant(getDateFormTime(time).toInstant(), ZoneId.systemDefault());
        return yyyyMMdd.format(localDateTime);
    }


    public static String getYYYYMMDDV2FromDateV2(Long time, SimpleDateFormat yyyyMMdd) {

        return yyyyMMdd.format(getDateFormTime(time));
    }

    /**
     * 从时间戳转化为时间
     *
     * @param time
     * @return
     * @throws ParseException
     */
    public static Date getDateFormTime(Long time) {
        try {
            String timeStr = dateFormat.format(time);
            return dateFormat.parse(timeStr);
        } catch (ParseException e) {
            return new Date();
        }
    }

    /**
     * 获取当天的第一秒
     * @param date
     * @return
     */
    public static Date getFirstTimeInDay(Date date) {
        return truncate(date, Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取当天的最后一秒
     * @param date
     * @return
     */
    public static Date getLastTimeInDay(Date date) {
        date =  truncate(date, Calendar.DAY_OF_MONTH);
        //加一天 减一毫秒
        date = org.apache.commons.lang3.time.DateUtils.addDays(date, 1);
        date = org.apache.commons.lang3.time.DateUtils.addMilliseconds(date, -1);
        return date;
    }

    public static Date truncate(Date date, int field) {
        return org.apache.commons.lang3.time.DateUtils.truncate(date, field);
    }

    public static Date addDays(Date date, int amount) {
        return org.apache.commons.lang3.time.DateUtils.addDays(date, amount);
    }

    public static Date addMonth(Date date, int amount) {
        return org.apache.commons.lang3.time.DateUtils.addMonths(date, amount);
    }

    public static Date addYear(Date date, int amount) {
        return org.apache.commons.lang3.time.DateUtils.addYears(date, amount);
    }

    public static Boolean isSameDay(Date date1, Date date2) {
        return org.apache.commons.lang3.time.DateUtils.isSameDay(date1, date2);
    }

    /**
     * 获取当前周的编号,从1开始
     * @param date
     * @return
     */
    public static Long getWeekNum(Date date) {
        Long day = (date.getTime() - ORIGIN_DATE.getTime()) / SECOND_OF_DAY;
        return day / DAYS_OF_WEEK + 1;
    }
    /**
     * 获取当前周的编号,从1开始
     * @param localDate
     * @return
     */
    public static Long getWeekNumV2(LocalDate localDate) {
        Long day = (localDateToMillTime(localDate).getTime() - ORIGIN_DATE.getTime()) / SECOND_OF_DAY;
        return day / DAYS_OF_WEEK + 1;
    }

    /**
     * 获取当天是本月的第几周
     * @param localDate 当前日期
     * @return
     */
    public static Long getWeekNumOnMonth(LocalDate localDate) {
        Date localDateToDate = localDateToMillTime(localDate);
        Date firstDay = getFirstDatOfMonth(localDateToDate);
        Date firstSunday = getFirstSunday(firstDay);
        if (localDateToDate.getTime() <= firstSunday.getTime()) {
            return 1L;
        }
        Long day = (localDateToDate.getTime()- firstSunday.getTime()) / SECOND_OF_DAY;
        return (day - 1) / DAYS_OF_WEEK + 2;
    }

    /**
     * 是否跨周
     * @param date1
     * @param date2
     * @return true没跨周，false 跨周
     */
    public static Boolean isSameWeek(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        //西方周日为一周的第一天，咱得将周一设为一周第一天
        cal1.setFirstDayOfWeek(Calendar.MONDAY);
        cal1.setTime(date1);
        cal2.setTime(date2);
        if (cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR))
            return true;
        return false;
    }

    /**
     * 获取特定周的周一时间
     */
    public static Integer getWeekMonByNum(int num) {
        Long day = (num - 1) * DAYS_OF_WEEK * SECOND_OF_DAY + ORIGIN_DATE.getTime();
        return getIntFromDate(getThisWeekMon(new Date(day)));
    }

    public static Date lastWeekDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -7);
        return calendar.getTime();
    }

    public static Date getYesterday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -1);
        return calendar.getTime();
    }

    public static int getIntFromDate(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
        String dataString = yyyyMMdd.format(date);
        return Integer.valueOf(dataString);
    }

    public static int getIntFromDateV2(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMM");
        String dataString = yyyyMMdd.format(date);
        return Integer.valueOf(dataString);
    }

    public static int getIntFromLocalDateV1(LocalDate date) {
        DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyy");
        String dataString = yyyyMMdd.format(date);
        return Integer.valueOf(dataString);
    }

    public static int getIntFromLocalDateV2(LocalDate date) {
        DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyyMMdd");
        String dataString = yyyyMMdd.format(date);
        return Integer.valueOf(dataString);
    }

    public static String getStringFromLocalDate(LocalDateTime localDateTime) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String localTime = df.format(localDateTime);
        return localTime;
    }

    public static String getStringMonthFromLocalDate(LocalDateTime localDateTime) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMM");
        String localTime = df.format(localDateTime);
        return localTime;
    }

    public static String getStringDayFromLocalDate(LocalDateTime localDateTime) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
        String localTime = df.format(localDateTime);
        return localTime;
    }


    public static int getIntFromLocalDateV3(LocalDate date) {
        DateTimeFormatter yyyyMM = DateTimeFormatter.ofPattern("yyyyMM");
        String dataString = yyyyMM.format(date);
        return Integer.valueOf(dataString);
    }

    public static Integer betweenMonths(LocalDate now, LocalDate first) {
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM");
        //未来时间
        YearMonth afterMonth = YearMonth.parse(sdf.format(now), sdf);
        // 过去时间
        YearMonth beforeMonth = YearMonth.parse(sdf.format(first), sdf);

        int monDif = afterMonth.getMonthValue() - beforeMonth.getMonthValue();

        int month = (afterMonth.getYear() - beforeMonth.getYear()) * 12;
        return monDif + month;
    }
    public static int getIntFromLocalDateV4(LocalDate date) {
        DateTimeFormatter MMdd = DateTimeFormatter.ofPattern("MMdd");
        String dataString = MMdd.format(date);
        return Integer.valueOf(dataString);
    }
    public static String getIntFromLocalDateV4_2(LocalDate date) {
        DateTimeFormatter yyyyMM = DateTimeFormatter.ofPattern("MM-dd");
        return yyyyMM.format(date);
    }

    public static String getIntFromYearDate(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy");
        String dataString = yyyyMMdd.format(date);
        return dataString;
    }

    public static int getIntFromMouthDate(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMM");
        String dataString = yyyyMMdd.format(date);
        return Integer.valueOf(dataString);
    }

    public static int getIntFromTwoWeeksBeforeDate(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
        String dataString = yyyyMMdd.format(addDays(new Date(), -13));
        return Integer.valueOf(dataString);
    }

    public static String getStrFromDateV2(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
        return yyyyMMdd.format(date);
    }

    public static String getStrFromDateV4(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy.MM.dd");
        return yyyyMMdd.format(date);
    }

    public static String getStrFromDateV5(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy年MM月dd日");
        return yyyyMMdd.format(date);
    }

    public static String getYYYYMMDDFromDate(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
        return yyyyMMdd.format(date);
    }

    public static String getYYYYMMDDFromDateV2(Date date) {
        DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyyMMdd");
        // 将 Date 转换成 JDK 8 中的时间类型 LocalDateTime
        LocalDateTime localDateTime =
                LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return yyyyMMdd.format(localDateTime);
    }

    public static String getYYYYMMFromDate(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMM");
        return yyyyMMdd.format(date);
    }

    public static String getYYYYMMDFromDate(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy.MM");
        return yyyyMMdd.format(date);
    }

    public static String getMMDDFromDate(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("MM.dd");
        return yyyyMMdd.format(date);
    }

    public static String getMMDDFromDateV2(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("MM-dd");
        return yyyyMMdd.format(date);
    }

    public static String getMMDDFromDateV3(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("MMdd");
        return yyyyMMdd.format(date);
    }

    public static String getStrFromDateV3(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return yyyyMMdd.format(date);
    }

    public static String getStrFromDateV6(Date date) {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return yyyyMMdd.format(date);
    }

    public static Date getDateFromStr(String date) throws ParseException {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return yyyyMMdd.parse(date);
    }

    public static Date getDateFromInt(int dateInt) throws ParseException {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
        return yyyyMMdd.parse(String.valueOf(dateInt));
    }


    //todo 这里需要优化一下
    public static int getIntFromLocalDate(LocalDate date) {
        int year = date.getYear();
        int month = date.getMonthValue();
        int dayOfMonth = date.getDayOfMonth();
        return year * 10000 + month * 100 + dayOfMonth;
    }

    public static Date getThisWeekMon(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);            //中国是以星期一作为一个星期的一天
        calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
        return calendar.getTime();
    }

    public static int getMonthNum(Date date) {
        SimpleDateFormat yyyyMM = new SimpleDateFormat("yyyyMM");
        String dataString = yyyyMM.format(date);
        return Integer.valueOf(dataString);
    }

    public static int getDayNum(Date date) {
        SimpleDateFormat yyyyMM = new SimpleDateFormat("yyyyMM");
        String dataString = yyyyMM.format(date) + "01";
        return Integer.valueOf(dataString);
    }

    public static List<Integer> getMonthNumInRange(Date startTime, Date endTime) {
        Integer posMonth = getMonthNum(startTime);
        Integer endTimeNum = getMonthNum(endTime);

        List<Integer> result = new ArrayList<>();
        while (posMonth <= endTimeNum) {
            result.add(posMonth);

            startTime = addMonth(startTime, 1);
            posMonth = getMonthNum(startTime);
        }

        return result;
    }

    public static int getYearNum(Date date) {
        SimpleDateFormat yyyy = new SimpleDateFormat("yyyy");
        String dataString = yyyy.format(date);
        return Integer.valueOf(dataString);
    }


    public static Date getLastMonthFirst(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH,-1);
        calendar.set(Calendar.DAY_OF_MONTH,1);
        return calendar.getTime();
    }

    public static Date getLastMonthLast(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH,-1);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }

    public static Date getLastYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, -1);
        return calendar.getTime();
    }

    public static Date getThisMonthFirst(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH,1);
        return calendar.getTime();
    }

    public static Date getThisMonthLast(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }


    public static Date valueOfInt(int ymd) throws ParseException {
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
        return yyyyMMdd.parse(String.valueOf(ymd));
    }


    public static Date getNextWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.WEEK_OF_YEAR,1);
        return calendar.getTime();
    }


    public static Date getNextMonthFirst(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH,1);
        calendar.set(Calendar.DAY_OF_MONTH,1);
        return calendar.getTime();
    }

    public static Date getNextDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR,1);
        return calendar.getTime();
    }

    public static Date getDayCustomHour(Date date, int hour) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getNextDawn0hour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR,1);
        calendar.set(Calendar.HOUR_OF_DAY,0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND,0);
        return calendar.getTime();
    }

    public static int getIntFromYearAndDay(int year, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.DAY_OF_YEAR, day);
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
        String dataString = yyyyMMdd.format(new Date(calendar.getTimeInMillis()));
        return Integer.valueOf(dataString);
    }

    public static boolean currentDay(Long time) {
        return getIntFromDate(new Date()) == getIntFromDate(new Date(time));
    }

    public static Boolean isMonday() {
        Date today = new Date();
        Date yesterday = DateUtils.getYesterday(today);
        Long weekNum = DateUtils.getWeekNum(yesterday);
        return !DateUtils.getWeekNum(today).equals(weekNum);
    }

    public static Boolean isMonday(Date date) {
        Date yesterday = DateUtils.getYesterday(date);
        Long weekNum = DateUtils.getWeekNum(yesterday);
        return !DateUtils.getWeekNum(date).equals(weekNum);
    }

    public static Boolean isSunday(Date date) {
        Date tomorrow = org.apache.commons.lang3.time.DateUtils.addDays(date, 1);
        Long weekNum = DateUtils.getWeekNum(tomorrow);
        return !DateUtils.getWeekNum(date).equals(weekNum);
    }

    public static Boolean isFirstDayOfMonth(Long time) {
        Date today = new Date(time);
        Date yesterday = DateUtils.getYesterday(today);
        int monthNum = DateUtils.getMonthNum(yesterday);
        return DateUtils.getMonthNum(today) != monthNum;
    }

    public static Boolean isFirstDayOfYear(Long time) {
        Date today = new Date(time);
        Date yesterday = DateUtils.getYesterday(today);
        int yearNum = DateUtils.getYearNum(yesterday);
        return DateUtils.getYearNum(today) != yearNum;
    }

    public static Boolean isLastDayOfMonth(Long time) {
        Date today = new Date();
        if(time != null && time != 0L) {
            today = new Date(time);
        }
        Date nextDay = DateUtils.getNextDay(today);
        int monthNum = DateUtils.getMonthNum(nextDay);
        return DateUtils.getMonthNum(today) != monthNum;
    }

    public static Boolean isToday(long time) {
        Calendar now = Calendar.getInstance();
        //毫秒数
        long ms = 1000L * (now.get(Calendar.HOUR_OF_DAY) * 3600L + now.get(Calendar.MINUTE) * 60L + now.get(Calendar.SECOND));
        long nowMs = now.getTimeInMillis();
        return nowMs - time < ms;
    }

    public static boolean beforeCurrentMonth(Long time) {
        return getMonthNum(new Date()) > getMonthNum(new Date(time));
    }



    //获取午夜时间，即23：59：59
    public static Date getMidnight(Date date) {
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        calender.set(Calendar.HOUR_OF_DAY, 23);
        calender.set(Calendar.MINUTE, 59);
        calender.set(Calendar.SECOND, 59);
        calender.set(Calendar.MILLISECOND, 999);
        return calender.getTime();
    }

    //获取黎明时间，即00：00：00
    public static Date getDawn(Date date) {
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        calender.set(Calendar.HOUR_OF_DAY, 0);
        calender.set(Calendar.SECOND, 0);
        calender.set(Calendar.MINUTE, 0);
        calender.set(Calendar.SECOND, 0);
        calender.set(Calendar.MILLISECOND, 0);
        return calender.getTime();
    }

    //获取这个月中最后一天的最后一分一秒。
    public static Date getMaxDayOfThisMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        Date maxDate = cal.getTime();
        return getMidnight(maxDate);
    }

    /**
     * 获取本周开始时间
     *
     * @param date
     * @return
     */
    public static Date getWeekStartTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);  //周日是第一天
        if (dayOfWeek == Calendar.SUNDAY) {
            dayOfWeek = 7;
        } else {
            dayOfWeek = dayOfWeek - 1;
        }
        calendar.add(Calendar.DAY_OF_WEEK, -dayOfWeek + 1);  //周一
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取本周周日开始时间
     *
     * @param date
     * @return
     */
    public static Date getWeekEndSundayTime(@NotNull Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);  //周日是第一天
        if (dayOfWeek == Calendar.SUNDAY) {
            dayOfWeek = 7;
        } else {
            dayOfWeek = dayOfWeek - 1;
        }
        calendar.add(Calendar.DAY_OF_WEEK, -dayOfWeek + 7);  //周日
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 判断是否是周一
     * @return
     */
    public static boolean isMondayInThisWeek(LocalDate now) {
        return LocalDate.now().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).equals(now);
    }



    /**
     * 判断当前日期是星期几
     * @param date
     * @return dayForWeek
     */
    public static int dayForWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayForWeek;
        if(calendar.get(Calendar.DAY_OF_WEEK) == 1) {
            dayForWeek = 7;
        } else {
            dayForWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        }
        return dayForWeek;
    }

    /**
     * 计算两个时间之间间隔的天数
     * @param beginDate
     * @param endDate
     * @return
     */
    public static int differentDays(Date beginDate, Date endDate) {
        int days = (int) (Math.abs(endDate.getTime() - beginDate.getTime()) / (1000 * 3600 * 24));
        return days;
    }

    /**
     * 2018-01-01 23:59:59 和 2018-01-02 00:00:00 相距一天
     * 计算两个时间之间间隔的天数
     */
    public static int differentDaysV2(Date startDate, Date endDate) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(startDate);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(endDate);
        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2) {//同一年
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {//闰年
                    timeDistance += 366;
                } else {//不是闰年
                    timeDistance += 365;
                }
            }
            return timeDistance + (day2 - day1);
        } else { //不同年
            return day2 - day1;
        }
    }

    public static LocalDate millTimeToLocalDate(long begin) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(begin), TimeZone.getDefault().toZoneId()).toLocalDate();
    }

    public static Date localDateToMillTime(LocalDate localDate){
        ZoneId zone = TimeZone.getDefault().toZoneId();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }

    public static Date localDateTimeToMillTime(LocalDateTime localDateTime){
        ZoneId zone = TimeZone.getDefault().toZoneId();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return Date.from(instant);
    }

    @NotNull
    public static Date getDayBegin(Date date){
        Assert.isTrue(null != date,"date cannot be empty!");
        return truncate(date, Calendar.DATE);
    }



    public static Date getFirstDatOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天
        return getDayBegin(calendar.getTime());
    }

    public static Date getLastMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        return getDayBegin(calendar.getTime());
    }


    /**
     * 获取上午8点的时间
     */
    public static Date getDayTime8(Date date) {
        Assert.isTrue(null != date, "date cannot be empty!");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 8);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static boolean isMonday(LocalDate localDate) {
        LocalDate now = LocalDate.now();
        now = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));

        return now.equals(localDate);
    }


    public static int getDifferenceMonths(Date start, Date end) {
        if (start.getTime() > end.getTime()) return 0;
        Calendar calendar = Calendar.getInstance();

        calendar.setTime(start);
        int startYear = calendar.get(Calendar.YEAR);
        int startMonth = calendar.get(Calendar.MONDAY);

        calendar.setTime(end);
        int endYear = calendar.get(Calendar.YEAR);
        int endMonth = calendar.get(Calendar.MONDAY);

        return (endYear - startYear) * 12 + (endMonth - startMonth);
    }

    public static int getDifferenceYears(Date start, Date end) {
        if (start.getTime() > end.getTime()) return 0;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(start);
        int startYear = calendar.get(Calendar.YEAR);
        calendar.setTime(end);
        int endYear = calendar.get(Calendar.YEAR);
        return endYear - startYear;
    }

    /**
     * 当年第一天
     * @param date
     * @return
     * @throws Exception
     */
    public static Date getFirstDayOfYear(Date date) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat format3 = new SimpleDateFormat("yyyy");
        String time1 = format3.format(date);
        return getDayBegin(format.parse(time1 + "-01-01"));

    }

    /**
     * 当年最后天
     */
    public static Date getLastDayOfYear(Date date) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat format3 = new SimpleDateFormat("yyyy");
        String time1 = format3.format(date);
        return getDayBegin(format.parse(time1 + "-12-31"));

    }

    /**
     * 获取指定日期所在年的过去月份
     */
    public static List<Integer> getMonthsInYear(Date date) {
        List<Integer> monthResult = new ArrayList<>();

        //获取日期当年的12月
        Calendar lastMonthOfYear = org.apache.commons.lang3.time.DateUtils.toCalendar(date);
        lastMonthOfYear.set(Calendar.MONTH, 12);

        //生成小于等于当前月份的数据
        Integer currentMonth = getMonthNum(new Date());
        Date month = lastMonthOfYear.getTime();
        for (int index = 0; index < 12; ++index) {
            month = addMonths(month, -1);
            int monthInt = getMonthNum(month);
            if (monthInt <= currentMonth) {
                monthResult.add(monthInt);
            }
        }

        return monthResult;
    }

    /**
     * 输入日期范围，分析范围内包含的完整月份信息，返回整数值
     */
    public static List<Integer> getMonthsByRange(Date startTime, Date endTime) {
        Date monthDate = startTime;
        Integer month;
        Integer endMonth = getMonthNum(endTime);
        List<Integer> result = new ArrayList<>();

        do {
            monthDate = addMonths(monthDate, 1);
            month = getMonthNum(monthDate);
            if (month < endMonth) {
                result.add(month);
            }
        } while (month < endMonth);

        return result;
    }

    public static List<Integer> getMonthsDayByRange(Date startTime, Date endTime) {
        Date monthDate = startTime;
        Integer month;
        Integer endMonth = getDayNum(endTime);
        List<Integer> result = new ArrayList<>();

        do {
            monthDate = addMonths(monthDate, 1);
            month = getDayNum(monthDate);
            if (month < endMonth) {
                result.add(month);
            }
        } while (month < endMonth);

        return result;
    }

    /**
     * 输入日期范围，分析范围内的月份信息，返回整数值
     * @param startTime 20200112
     * @param endTime 20200323
     * @return [202001, 202002, 202003]
     */
    public static List<Integer> getMonthsByRangeV2(Date startTime, Date endTime) {
        Date startMonth = DateUtils.truncate(startTime, Calendar.MONTH);
        Date endMonth = DateUtils.truncate(endTime, Calendar.MONTH);
        Date current = startMonth;
        List<Integer> result = new ArrayList<>();
        while (!current.after(endMonth)) {
            result.add(getMonthNum(current));
            current = DateUtils.addMonth(current, 1);
        }
        return result;
    }

    /**
     * 输入日期范围，返回其实月到结束月
     * @param startTime 20200112
     * @param endTime 20203-23
     * @return [2020-01-01, 2020-02-01, 2020-03-01]
     */
    public static List<String> getStrMonthsByRange(Date startTime, Date endTime) {
        Date startMonth = DateUtils.truncate(startTime, Calendar.MONTH);
        Date endMonth = DateUtils.truncate(endTime, Calendar.MONTH);
        Date current = startMonth;
        List<String> result = new ArrayList<>();
        while (!current.after(endMonth)) {
            result.add(getStrFromDateV2(current));
            current = DateUtils.addMonth(current, 1);
        }
        return result;
    }

    /**
     * 输入日期范围，分析范围内包含的完整周，返回整数值
     */
    public static List<Integer> getWeeksByRange(Date startTime, Date endTime) {
        Long startWeekNum = DateUtils.getWeekNum(startTime);
        Long endWeekNum = getWeekNum(endTime);
        Integer weekNum = startWeekNum.intValue();
        List<Integer> result = new ArrayList<>();
        while (weekNum <= endWeekNum) {
            result.add(weekNum);
            weekNum++;
        }
        return result;
    }

    /**
     * 输入日期范围，分析范围内不包含在完整月份内的天信息，返回整数值
     * 例如： 20180830 ~ 20181002 -> 20180830,20180831,20181001,20181002
     */
    public static Set<Integer> getboundDaysByRange(Date startTime, Date endTime) {
        Set<Integer> result = new HashSet<>();
        int startTimeInt = getIntFromDate(startTime);
        int endTimeInt = getIntFromDate(endTime);

        //获取开始月份的数据
        Date nextMonthFirstDay = org.apache.commons.lang3.time.DateUtils.setDays(addMonths(startTime, 1), 1);
        int nextMonthFirstDayInt = getIntFromDate(nextMonthFirstDay);
        for (int index = 0; index < 31; ++index) {
            int dayInt = getIntFromDate(addDays(startTime, index));
            if (dayInt < nextMonthFirstDayInt && dayInt <= endTimeInt) {
                result.add(dayInt);
            }
        }

        //获取结束月份的数据
        Date endMonthFirstDay = org.apache.commons.lang3.time.DateUtils.setDays(endTime, 1);
        int endDayInt = getIntFromDate(endTime);
        for (int index = 0; index < 31; ++index) {
            int dayInt = getIntFromDate(addDays(endMonthFirstDay, index));
            if (dayInt <= endDayInt && dayInt > startTimeInt) {
                result.add(dayInt);
            }
        }

        return result;
    }

    /**
     * 输入日期范围，分析范围内不包含在完整月份内的天信息，返回字符格式
     * 例如： 2018-08-30 ~ 2018-10-02 -> 2018-08-30,2018-08-31,2018-10-01,2018-10-02
     */
    public static Set<String> getBoundDaysByRangeV2(Date startTime, Date endTime) {
        Set<String> result = new HashSet<>();
        int startTimeInt = getIntFromDate(startTime);
        int endTimeInt = getIntFromDate(endTime);

        //获取开始月份的数据
        Date nextMonthFirstDay = org.apache.commons.lang3.time.DateUtils.setDays(addMonths(startTime, 1), 1);
        int nextMonthFirstDayInt = getIntFromDate(nextMonthFirstDay);
        for (int index = 0; index < 31; ++index) {
            int dayInt = getIntFromDate(addDays(startTime, index));
            if (dayInt < nextMonthFirstDayInt && dayInt <= endTimeInt) {
                result.add(getStrFromDateV2(addDays(startTime, index)));
            }
        }

        //获取结束月份的数据
        Date endMonthFirstDay = org.apache.commons.lang3.time.DateUtils.setDays(endTime, 1);
        int endDayInt = getIntFromDate(endTime);
        for (int index = 0; index < 31; ++index) {
            int dayInt = getIntFromDate(addDays(endMonthFirstDay, index));
            if (dayInt <= endDayInt && dayInt > startTimeInt) {
                result.add(getStrFromDateV2(addDays(endMonthFirstDay, index)));
            }
        }

        return result;
    }

    /**
     * 输入日期范围，将日期转换为每天的集合，左闭区间、右闭区间
     * [yyyyMMdd, yyyyMMdd]
     */
    public static List<Integer> getDaysByRange(Date startTime, Date endTime) {
        List<Integer> result = new ArrayList();
        Date currentTime = startTime;
        while (currentTime.getTime() <= endTime.getTime()) {
            int currentTimeInt = getIntFromDate(currentTime);
            result.add(currentTimeInt);
            currentTime = org.apache.commons.lang3.time.DateUtils.addDays(currentTime, 1);
        }
        return result;
    }

    /**
     * 获得日期当日的开始时间
     */
    public static Date getStartOfDay(Date date) {
        Date yesterday = addDays(date, -1);
        return org.apache.commons.lang3.time.DateUtils.ceiling(yesterday, Calendar.DATE);
    }

    /**
     * 获得日期当日的结束时间
     */
    public static Date getEndOfDay(Date date) {
        Date tomorrowStart = org.apache.commons.lang3.time.DateUtils.ceiling(date, Calendar.DATE);
        return addSeconds(tomorrowStart, -1);
    }

    /**
     * 按天获取区间内的所有时间
     */
    public static List<Integer> getDaysInRange(Date startTime, Date endTime) {
        Integer startTimeInt = getIntFromDate(startTime);
        Integer endTimeInt = getIntFromDate(endTime);

        List<Integer> result = new ArrayList<>();
        while (startTimeInt <= endTimeInt) {
            result.add(startTimeInt);
            startTime = addDays(startTime, 1);
            startTimeInt = getIntFromDate(startTime);
        }

        return result;
    }


    /**
     * 将时间转换为传入时间月的第一天(YYYYMMDD)字符串
     * @param ymd 传入的时间
     */
    public static String formatYYYYMMDDFirstDayOfMonthByYMDInt(Integer ymd) throws ParseException {
        Date date = valueOfInt(ymd);
        Date firstDay = DateUtils.getThisMonthFirst(date);
        return getYYYYMMDDFromDate(firstDay);
    }

    public static String formatYYYYMMDDFirstDayOfMonthByDate(Date date) throws ParseException {
        Date firstDay = DateUtils.getThisMonthFirst(date);
        return getYYYYMMDDFromDate(firstDay);
    }

    public static String formatYYYYMMDDFirstDayOfMonthWeekNum(Integer weekNum) throws ParseException {
        long time = (weekNum - 1) * DAYS_OF_WEEK * SECOND_OF_DAY + ORIGIN_DATE.getTime();
        Date firstDay = DateUtils.getThisMonthFirst(new Date(time));
        return getYYYYMMDDFromDate(firstDay);
    }


    /**
     * 获取下学期的开始时间 0201
     *
     * @param nowDate
     * @return
     */
    public static Date getNextSemester(Date nowDate) {
        Calendar c = Calendar.getInstance();
        c.setTime(truncate(nowDate, Calendar.MONTH));
        c.set(Calendar.MONTH, 1);
        return c.getTime();
    }

    /**
     * 获取上一年的上学期开始时间  0801
     *
     * @param nowDate
     * @return
     */
    public static Date getLastYearLastSemester(Date nowDate) {
        Calendar c = Calendar.getInstance();
        c.setTime(truncate(nowDate, Calendar.MONTH));
        c.add(Calendar.YEAR, -1);
        c.set(Calendar.MONTH, 7);
        return c.getTime();
    }

    /**
     * 获取今年的上学期开始时间  0801
     *
     * @param nowDate
     * @return
     */
    public static Date getThisYearLastSemester(Date nowDate) {
        Calendar c = Calendar.getInstance();
        c.setTime(truncate(nowDate, Calendar.MONTH));
        c.set(Calendar.MONTH, 7);
        return c.getTime();
    }

    /**
     * 获取n年前的时间
     *
     * @param nowDate
     * @return
     */
    public static Date getLastNYear(Date nowDate, Integer n) {
        Calendar c = Calendar.getInstance();
        c.setTime(truncate(nowDate, Calendar.MONTH));
        c.add(Calendar.YEAR, -n);
        return c.getTime();
    }

    /**
     * 获取指定日期开始的第一个周日
     *
     * @param first
     */
    public static Date getFirstSunday(Date start) {
        Calendar c = Calendar.getInstance();
        c.setTime(start);
        while (c.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
            c.add(Calendar.DATE, 1);
        }
        return c.getTime();
    }
}